package com.szwistar.common.datastruct;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.szwistar.common.os.FileUtils;

public class XmlParser {
	public static XmlParser open(InputStream in) throws Exception {
	    DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
	    Document xml = db.parse(in); in.close();
	    return new XmlParser(xml);
	}

	public static XmlParser open(File xmlFile) throws Exception {
	    DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
	    Document xml = db.parse(xmlFile);
	    return new XmlParser(xml);
	}

	public static XmlParser open(String xmlString) throws Exception {
		return open(new ByteArrayInputStream(xmlString.getBytes()));
	}

	protected Document xml;

	private XmlParser(Document xml) {
		this.xml = xml;
	}

	/**
	 * 获取命名的子节点
	 * @param node 父节点
	 * @param name 子节点名称
	 * @param idx 第几个
	 * @return
	 */
	protected Node getChildByName(Node node, String name, int idx) {
		NodeList nodes = node.getChildNodes();
		int count = 0;
		for(int i=0; i<nodes.getLength(); i++) {
			Node child = nodes.item(i);
			if(child.getNodeName().equalsIgnoreCase(name)) {
				if(idx == count) {
					return child;
				} else {
					count++;
				}
			}
		}
		return null;
	}

	/**
	 * 根据节点路径获取节点
	 * @param nodePath 节点路径，例如：<br>
	 * <li>"hbuilder/apps/1:app" 表示 <hbuilder><apps>下的第2个<app>节点，<br>
	 * <li>"hbuilder/apps/app" 表示 <hbuilder><apps>下的第1个默认<app>节点
	 * @return
	 */
	protected Node getNode(String nodePath) {
		String[] parts = nodePath.split("/");
		Node node = xml;
		for(String part: parts) {
			Node child = null;
			String[] sub = part.split(":");
			if(sub.length == 2) {
				int idx = -1;
				try { idx = Integer.parseInt(sub[0]); } catch(Exception e) {}
				if(idx >= 0) {
					child = getChildByName(node, sub[1], idx);
				} else {
					return null;
				}
			} else {
				child = getChildByName(node, part, 0);
			}

			if(child == null) { return null; }
			node = child;
		}
		return node;
	}

	/**
	 * 获取节点属性
	 * @param nodePath 节点路径，例如：<br>
	 * <li>"hbuilder/apps/1:app" 表示 <hbuilder><apps>下的第2个<app>节点，<br>
	 * <li>"hbuilder/apps/app" 表示 <hbuilder><apps>下的第1个默认<app>节点
	 * @param attribute 节点属性名称
	 * @param defaultValue 默认值
	 * @return
	 */
	public String getAttribute(String nodePath, String attribute, String defaultValue) {
		Node node = getNode(nodePath);
		if(node == null) { return defaultValue; }

		node = node.getAttributes().getNamedItem(attribute);
		if(node == null) { return defaultValue; }

		String value = node.getNodeValue();
		return value != null ? value : defaultValue;
	}

	/**
	 * 获取节点中的值
	 * @param nodePath 节点路径，例如：<br>
	 * <li>"hbuilder/apps/1:app" 表示 <hbuilder><apps>下的第2个<app>节点，<br>
	 * <li>"hbuilder/apps/app" 表示 <hbuilder><apps>下的第1个默认<app>节点
	 * @param defaultValue 默认值
	 * @return
	 */
	public String getValue(String nodePath, String defaultValue) {
		Node node = getNode(nodePath);
		if(node == null) { return defaultValue; }

		String value = node.getFirstChild().getNodeValue();
		return value != null ? value : defaultValue;
	}

	// for test only
	public static void main(String argv[]) throws Exception {
		/* xxx.xml:
		<hbuilder version="1.9.9.69757" debug="true" syncDebug="true">
		    <apps>
		        <app appid="HelloH5" appver="">test</app>
		        <app appid="xxx2" appver="">test2</app>
		    </apps>
		</hbuilder>
		*/
		String str = FileUtils.readFileAsString("xxx.xml");
		XmlParser xml = open(str);
		str = xml.getAttribute("hbuilder/apps/app", "appid", null);
		System.out.print(str);	// xxx2
		str = xml.getValue("hbuilder/apps/0:app", null);
		System.out.print(str);	// test
	}
}
